﻿namespace egret3d {
    export class ParticleSystem {
        private fps: number = 60;
        private time: number;

        private meshBatchers: Array<MeshBatcher>;
        private curMeshBatcher: MeshBatcher;
        private curMat: MaterialBase;
        private lastMat: MaterialBase;
        private shapeCount: number;
        view: View3D;

        deltaTime: number = 1000 / this.fps;

        constructor(_view: View3D)
        {
            this.time = 0;
            this.shapeCount = 0;
            this.view = _view;
            this.meshBatchers = new Array<MeshBatcher>();
            this.start();
        }
        mapUpdate: { [id: number]: (particle: Particle, time: number) => void } = {};
        setMat(_mat: MaterialBase)
        {
            this.curMat = _mat;
        }

        creatMeshbatcher(gem: Geometry, mat: MaterialBase)
        {
            var mesh: Mesh = new Mesh(gem, mat);
            var meshBatchers = new MeshBatcher(mesh);

            this.curMeshBatcher = meshBatchers;
            this.meshBatchers.push(meshBatchers);

            this.view.addChild3D(this.curMeshBatcher.mesh);
        }

        addParticleByType(type: string, particleUpdate: (particle: Particle, time: number)=> void, count: number = 1)
        {
            var particleShape: ParticleShape = MeshBatcherMgr.instance().getshape(type);

            this.addParticleByShape(particleShape, particleUpdate, count);
        }

        addParticleByShape(particleShape: ParticleShape, particleUpdate: (particle: Particle, time: number) => void, count: number = 1)
        {
            if (this.curMat != this.lastMat)
            {
                //更换了mat 更换batcher
                var gem = new Geometry();
                gem.drawType = Context3DProxy.gl.DYNAMIC_DRAW;
                this.creatMeshbatcher(gem, this.curMat);

                this.lastMat = this.curMat;
            }

            if (this.curMeshBatcher.vercount + particleShape.vertexCount * count > this.curMeshBatcher.maxvercount)
            {
                //mesh buffer达到上限也要更换batcher
                var gem = new Geometry();
                gem.drawType = Context3DProxy.gl.DYNAMIC_DRAW;
                this.creatMeshbatcher(gem, this.lastMat);
            }


            for (var i = 0; i < count; i++)
            {
                var p1 = this.curMeshBatcher.AddParticleByShape(particleShape, this.shapeCount);
            }
            this.mapUpdate[this.shapeCount] = particleUpdate;
            this.shapeCount++;
        }

        start() {
            let that = this;
            setInterval(() => {
                that.update();
            }, 1000 / this.fps);
        }
        update() {
            this.time += this.deltaTime;
            for (var i = 0; i < this.meshBatchers.length; i++)
            {
                var batchers = this.meshBatchers[i];

                if (!batchers.active)
                {
                    this.view.removeChild3D(batchers.mesh);
                    batchers.dispose();
                    continue;
                }

                for (var j = 0; j < batchers.parlist.length; j++)
                {
                    var p = batchers.parlist[j];
                    var fun = this.mapUpdate[p.shapeID];
                    fun(p, this.deltaTime / 1000);
                }

                batchers.update(this.deltaTime / 1000);
            }
        }
    }
}

